//--------------------------------------------------------------------------------------------------
//										Lista / Combo
//--------------------------------------------------------------------------------------------------

//El custom drop down list original se reemplazo por un drop down list standard al cual se le aplicara una jquery library para customizarlo
//Se mantendra un array con la seleccion de los items (0 no seleccionado, 1 seleccionado)
//y una propiedad selected que reflejara la ultima seleccion

//TODO: remove selecteds logic. keep this under select2 responsability.

var ComboList_Instances = new Array();

function WebComboList(id)
{
	ComboList_Instances[id]	 = this;

	//Atributos publicos
	this.width           = 150;     // en pixels
	this.multiple        = false;   // multiple seleccion
	this.size			 = 5;       // en cantidad de items
	this.labelclear		 = ""; 
	this.cssClass        = "";
	
	this.multiselect	 = false;
	this.redraw			 = true;
	
	//Atributos privados
	this.id				= id;
	this.items			= new Array();
	this.count			= 0;
	this.text   		= "";
		
	// en la lista son los items seleccionados, en los combos son los items pintados
	this.selecteds		= new Array();

    // en las listas es el ultimo item seleccionado, en los combos es el ! item seleccionado
	this.selected		= -1;   
	
	this.resizable		= false;
	this.container		= "";
	this.pathimages		= "";
	this.iswritten		= false;
	this.enabled		= true;

	this.emptyText = "Select...";
    
    // Note [radio buttons]. esto es un parche. deberia haber un control separado para esto.
	this.radioButtons   = false;
    
	// Funciones publicas
	this.Dispose		= ComboList_Dispose;
	this.Clone		    = ComboList_Clone;
	this.AddItem 		= ComboList_AddItem;
	this.RemoveItem		= ComboList_RemoveItem;
	this.ClearList		= ComboList_ClearList;
	this.GetValueList	= ComboList_GetValueList;
	this.GetCaptionList	= ComboList_GetCaptionList;
	this.GetValue  		= ComboList_GetValue;
	this.GetCaption		= ComboList_GetCaption;
	this.SetValue 		= ComboList_SetValue;
	this.SetCaption		= ComboList_SetCaption;
	this.GetIndex		= ComboList_GetIndex;	
	this.Show 			= ComboList_ShowList;
	this.ShowIn 		= ComboList_ShowListIn;	
	this.SelectItem		= ComboList_SelectItem;
	this.Unselect		= ComboList_Unselect;
	this.Refresh		= ComboList_Refresh;
	this.Enable			= ComboList_Enable;
	this.Disable		= ComboList_Disable;
	
    this.ClearDescription = ComboList_ClearDescription;

    this.markControl = ComboList_MarkControl;
    
	// Eventos Personalizados
	this.evalOnChange = ComboList_EvalOnChange;
	this.onChange;
}

function ComboList_Dispose()
{
	var i;
	var childNodes = this.container.childNodes.length;
	
	for(i=0;i<childNodes;i++)
		this.container.removeChild(this.container.childNodes[0]);

	delete ComboList_Instances[this.id];
}

function ComboList_Clone(newId)
{
    var newCombo = new WebComboList(newId);

	newCombo.width = this.width;
	newCombo.size = this.size;
	newCombo.labelclear = this.labelclear;
	newCombo.multiselect = this.multiselect;
	newCombo.redraw = this.redraw;
    newCombo.cssClass = this.cssClass;
    newCombo.pathImages = this.pathImages;    
    
	newCombo.items = this.items.slice();
	newCombo.count = this.count;
		
	newCombo.resizable = this.resizable;
	newCombo.enabled = this.enabled;
    newCombo.onChange = this.onChange;
		
    newCombo.emptyText = this.emptyText;
    newCombo.multiple = this.multiple;
    newCombo.radioButtons = this.radioButtons;
    
	return newCombo;
}

//Esta funcion permite agregar un item a la lista
function ComboList_AddItem(value, caption, selected)
{
	var s = 0;
	
	//No se permiten agregar item con el value duplicado
	if (this.GetIndex(value)!=-1) 
	    return -1;

	this.items[this.count] = new Array(value, caption);
	
	if (selected) {
		s = 1;
	    this.selected = this.count;
	}
	
	this.selecteds[this.count] = s;
	this.count++;

	this.Refresh();
}

//Esta funcion permite eliminar un item a la lista
function ComboList_RemoveItem(value)
{
	var i = 0;
    var index = this.GetIndex(value);

	if (index==-1) return -1;

	for (i=index;i<this.count-1;i++) {
		this.items[i] = this.items[i+1];
		this.selecteds[i] = this.selecteds[i+1];
	}
    
	this.count--;
	
	if (this.selected==index) 
		this.selected = -1;
	else if (this.selected>index)
		this.selected--;
	
	this.Refresh();
}

//Limpia la lista de items
function ComboList_ClearList() {
	this.items.length = 0;
	this.selecteds.length = 0;
	this.selected = -1;
	this.count = 0;
	
	this.Refresh();
	
	if (this.redraw) 
	    ComboList_Eval(this);
}

//Esta funcion permite seleccionar un item en forma externa
function ComboList_SelectItem(value, skipOnChange)
{
	var i = 0;
	var index = 0;
	var encontro = false
	var campo = document.getElementById(this.id);

    // busco el item
	while ((i<this.count) && (!encontro)) {
		encontro = (value == this.items[i][0]);
		i++;
	}
    
	if (!encontro)
	    return -1;

    // refresco los selecteds
	if (!this.multiple) {
	    index = i-1;
	    for (i=0; i<this.count; i++) {
		    this.selecteds[i] = 0;
	    }
	}
    
	this.selecteds[index] = 1;
	this.selected = index;
	
	// actualizo el valor a mostrar
	if(campo)
	    campo.value = this.items[index][0];

	// refresh si la lista ya esta dibujada
	this.Refresh();
	
	// si corresponde evaluo el onChange
	if(!skipOnChange)
	    ComboList_Eval(this);
}

//Esta funcion vacia la seleccion de la lista
function ComboList_Unselect()
{
	var i;
	
	this.selected = -1;
	
	for(i=0; i<this.count; i++)	{
		this.selecteds[i] = 0;
	}
	
	//Refresh si la lista ya esta dibujada
    this.Refresh();

    // si corresponde evaluo el onChange
    if (this.redraw) 
        ComboList_Eval(this);
}

//Esta funcion permite obtener la descripcion de un item recibiendo como parametro su pos
function ComboList_GetCaption(index)
{
	if ((index<0) || (index>=this.count)) return -1;
	if (!this.iswritten) return("");
	
	return(this.items[index][1]);
}

//Esta funcion permite obtener el valor de un item recibiendo como parametro su pos
function ComboList_GetValue(index)
{
	if ((index<0) || (index>=this.count)) return -1;
	if (!this.iswritten) return -1;
	
	return(this.items[index][0]);
}

//Esta funcion permite escribir la descripcion de un item recibiendo como parametro su pos
function ComboList_SetCaption(index, caption)
{
	if ((index<0) || (index>=this.count)) return -1;
	if (!this.iswritten) return("");
	
	this.items[index][1] = caption;
	
	this.Refresh();
}

//Esta funcion permite reescribir el value de un item recibiendo como parametro su pos
function ComboList_SetValue(index, value)
{
	if ((index<0) || (index>=this.count)) return -1;
	if (!this.iswritten) return("");
	
	this.items[index][0] = value;
	
	this.Refresh();
}

//Esta funcion devuelve la pos de un item determinado, segun su value (si no existe develve -1)
function ComboList_GetIndex(value)
{
	var i = 0;
	var encontro = false;

	while ((i<this.count) && (!encontro)) {
		encontro = (value == this.items[i][0]);
		i++;
	}

	if (!encontro)
	    return -1;
	else
		return i-1;
}

//Esta funcion permite obtener el valor de la lista 
//segun los items que se encuentran seleccionados
function ComboList_GetValueList()
{
	var i;
	var stritem = "";
	
	// seleccion multiple
	if (this.multiple) {
		for (i=0; i<this.count; i++) {
			if (this.selecteds[i]) {
				stritem = stritem+this.items[i][0] + ",";
			}	
		}	
	}
	// seleccion simple
	else {
		if( (this.selected>=0) && (this.selected<this.count) )
			stritem = this.items[this.selected][0];
	}

    return (stritem);
}

//Esta funcion permite obtener el caption de la lista 
//segun los items que se encuentran seleccionados
function ComboList_GetCaptionList()
{
	var i;
	var stritem = "";
	
    // seleccion multiple
	if (this.multiple) {
		for (i=0; i<this.count; i++) {
			if (this.selecteds[i]) {
				stritem=stritem+this.items[i][1]+",";
			}	
		}	
	}
	// seleccion simple
	else {
		if( (this.selected>=0) && (this.selected<this.count) )
			stritem = this.items[this.selected][1];
	}

    return (stritem);
}

//Muestra la lista
function ComboList_ShowList(containerID, pathimages)
{
	if (this.iswritten) 
	    return -1;
	if (!document.getElementById(containerID))
	    return -1;
	
	if (this.resizable)	
	    ComboList_Resize(this);
	
	this.container  = document.getElementById(containerID);
	this.pathimages = pathimages;
	
	ComboList_ShowListAux(this);

	this.iswritten = true;
}

//Muestra la lista
function ComboList_ShowListIn(container, pathimages)
{
	if (this.iswritten) 
	    return -1;
	
	this.container  = container;
	this.pathimages = pathimages;
	
	ComboList_ShowListAux(this);

	this.iswritten = true;
}

//Muestra la lista escribiendola en el contenedor
function ComboList_ShowListAux(obj) 
{
    if (obj.radioButtons) {
        ComboList_ShowListAuxRadioButtons(obj);
    }
    else {
        ComboList_ShowListAuxSelect2(obj);
    }
}

// Note [radio buttons]
function ComboList_ShowListAuxRadioButtons(obj) {
    var html = "";
    var disabled = (obj.enabled) ? "" : " disabled=\"disabled\" ";
    var selected = "";
    var func = " onclick=\"ComboList_RefreshRadioButtons(this, '" + obj.id + "');\" ";

    for (i = 0; i < obj.count; i++) {
        if (obj.selecteds[i])
            selected = "checked=\"checked\"";
        else
            selected = "";

        html += "<span><input type=\"radio\" id=\"" + obj.id + "." + i + "\" name=\"" + obj.id + "\" " + disabled + func + " value=\"" + obj.items[i][0] + "\" " + selected + "/>" + obj.items[i][1] + "</span>";
    }

    html += ComboList_Struct(obj);

    $(obj.container).html(html);
}

function ComboList_ShowListAuxSelect2(obj) {
    var disabled = (obj.enabled) ? "" : "disabled=\"disabled\"";
    var multipleStr = (obj.multiple ? " multiple " : "");
    var html = "<select id=\"" + obj.id + "\" name=\"" + obj.id + "\" " + disabled + " style=\"width:" + obj.width + "px\" " + multipleStr + ">";
    var selected = "";

    // Note: deseleccion en combos
    // parche para combos estaticos que a priori no agregan el item vacio al principio
    /*
    if (obj.items[0][0] != "") {
        obj.items.unshift(new Array("", obj.emptyText));
        obj.count++;
    }
    */
    
    html += "<option></option>";
    
    for (i = 0; i < obj.count; i++) {
        if (obj.selecteds[i])
            selected = "selected=\"selected\"";
        else
            selected = "";

        html += "<option value=\"" + obj.items[i][0] + "\" " + selected + ">" + obj.items[i][1] + "</option>";
    }

    html += "</select>";

    html += ComboList_Struct(obj);

    $(obj.container)
        .html(html) // draw html
        .find("select") // find select element
        .select2({
            //apply select2 plugin
            minimumResultsForSearch: -1,
            // placeholderOption: 'first'
            placeholder: obj.emptyText,
            allowClear: true
        })
        .on("change", function() {
            ComboList_RefreshSelecteds(obj.id);
        });

        $(obj.container).on("select2-focus", function (e) {
            ComboList_SetFocus(this.id, e);
        });
}

function ComboList_SetFocus(id, e) {
    var mcombolist = ComboList_Get(id);

    if ((mcombolist) && (mcombolist.enabled)) {
        FocusManager.disposeFocus(e);
    }
}

//Refresca toda la lista 
function ComboList_Refresh()
{
	if (this.redraw) {
		if (this.iswritten) {
			ComboList_ShowListAux(this);
		}
	}
}

//Activo la lista
function ComboList_Enable() {
    this.enabled = true;
    
    if (this.iswritten)
        this.Refresh();
}

//Desactivo la lista
function ComboList_Disable() {
    this.enabled = false;
    
    if (this.iswritten)
        this.Refresh();
}

//Borro el texto del combo si no hay ningun item seleccionado (solo para combos editables)
function ComboList_ClearDescription() {
    var obj = document.getElementById(this.id);
    $(obj).select2('text', "");
}


//--------------Funciones Privadas

//Esta funcion sirve para refrescar el value del campo oculto que almacenara un string que contiene la estructura de la lista serializada
//esto servira para recuperar la estructura del lado del server
function ComboList_Struct(obj)
{
	var i;
	var values		= "";
	var captions	= "";
	var selecteds	= "";
	var html		= "";
	
	for (i=0; i<obj.count; i++)	{
		values	  += obj.items[i][0] + "|";
		captions  += obj.items[i][1] + "|";
		selecteds += obj.selecteds[i] + "|";
	}
	
	values = values.substring(0, values.length-1); 
	selecteds = selecteds.substring(0, selecteds.length-1); 

	html += "<input type=\"hidden\" id=\""+obj.id+"_values\" name=\""+obj.id+"_values\" value=\""+values+"\" private=\"yes\">";
	html += "<input type=\"hidden\" id=\""+obj.id+"_captions\" name=\""+obj.id+"_captions\" value=\""+captions+"\" private=\"yes\">";
	html += "<input type=\"hidden\" id=\""+obj.id+"_selecteds\" name=\""+obj.id+"_selecteds\" value=\""+selecteds+"\" private=\"yes\">";
	
	return (html);
}

//Esta funcion sirve para refrescar el value del campo oculto que almacenara un string que contiene 
//la configuracion de items seleccionados
function ComboList_RefreshStruct(obj)
{
    var selecteds = "";
    
	for (i=0; i<obj.count; i++)	{
		selecteds += obj.selecteds[i] + "|";
	}
	
	selecteds = selecteds.substring(0, selecteds.length-1); 
	
    var objSelecteds = document.getElementById(obj.id+"_selecteds");
    objSelecteds.value = selecteds;
}

//Esta funcion permite volver a evaluar el item seleccionado
//(lo que desencadenara la llamada a onchange y el rellenado de la lista relacionada, si la hubiera)
function ComboList_Eval(obj)
{
	if (obj.iswritten)
        obj.evalOnChange();
}


//-------------Manejo de Eventos

function ComboList_GetItemFromValue(id, value)
{
	var comboList = ComboList_Get(id);
	var encontro = false;
	var i = 0;
	
	if(value=="") return -1;
	
	// busqueda secuencial
	while( (!encontro) && (i<comboList.count)) {
	    var itemValue = comboList.items[i][1].toUpperCase();
    	encontro = (itemValue.indexOf(value.toUpperCase())==0);
    	i++;
	}
	
	if(encontro)
	    return (i-1);
    else
	    return -1;
}

// Note [radio buttons]
function ComboList_RefreshRadioButtons(obj, id) {
    var comboList = ComboList_Get(id);
    var value = $(obj).val();
    var lselected = comboList.selected;

    for (var i = 0; i < comboList.count; i++) {
        comboList.selecteds[i] = 0;
        comboList.selected = -1;
    }

    comboList.selected = ComboList_RefreshSelecteds_SelectItem(comboList, value);

    if (lselected != comboList.selected)
        comboList.evalOnChange();
}

function ComboList_RefreshSelecteds(id) {
    var comboList = ComboList_Get(id);
    var obj = document.getElementById(comboList.id);
    var data = $(obj).select2('data');
    var lselected = comboList.selected;
    var i;
    
    for (i = 0; i < comboList.count; i++) {
        comboList.selecteds[i] = 0;
        comboList.selected = -1;
    }
    
    if (comboList.multiple) {
        for (i = 0; i < data.length; i++) {
            ComboList_RefreshSelecteds_SelectItem(comboList, data[i].id);
        }
        
        comboList.evalOnChange();
    }
    else {
        if (data == null)
            comboList.selected = -1;
        else
            comboList.selected = ComboList_RefreshSelecteds_SelectItem(comboList, data.id);
        
        if (lselected != comboList.selected)
            comboList.evalOnChange();
    }
}

function ComboList_RefreshSelecteds_SelectItem(obj, value) {
    var i = 0;
    var encontro = false;
    
    while ((i < obj.count) && (!encontro)) {
        encontro = (value == obj.items[i][0]);
        i++;
    }

    if(encontro) {
        obj.selecteds[i - 1] = 1;
        return i - 1;
    }
    else {
        return -1;
    }
}


//----------------Eventos Personalizados

function ComboList_EvalOnChange()
{
    eval(this.onChange);
}


//---------------Validator

function ComboList_MarkControl(ok) {
    if (ok)
        $("#cont_" + this.id).removeClass("error");
    else
        $("#cont_" + this.id).addClass("error");
}


//---------------Funciones Externas

//Esta funcion devuelve la lista correspondiente al id pasado como parametro
function ComboList_Get(id)
{
    return (ComboList_Instances[id]);
}
